/****************************************************
	文件：CoroutineCtrl.cs
	作者：HuskyT
	邮箱：1005240602@qq.com
	日期：2021/1/2 14:25:6
	功能：协程管控制器
*****************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using HTFW.Utility.Global;
using UnityEngine;

namespace HTFW.Core
{
    public class CoroutineService : Singleton<CoroutineService>, IService
    {
        MonoBehaviour mMono;
        List<IRoutineHandle> mRoutineLst;
        ObjectPool<IRoutineHandle> mRoutinePool;

        public void Init(params object[] args)
        {
            mMono = (MonoBehaviour) args[0];
            mRoutineLst = new List<IRoutineHandle>();
            mRoutinePool = new ObjectPool<IRoutineHandle>(20, (pool) => { return new RoutineHandle(); },
                (routine) => { }, (routine) => { });
        }

        public void Dispose()
        {
            StopAll();
            mRoutinePool.Dispose();
            mMono = null;
        }

        /// <summary>
        /// 开启协程
        /// </summary>
        /// <param name="routine">协程</param>
        /// <param name="autoStartNow">是否即刻自动开启协程</param>
        /// <returns></returns>
        public IRoutineHandle Start(IEnumerator routine, bool autoStartNow = true)
        {
            var rou = mRoutinePool.Spawn();
            rou.Init(routine, autoStartNow);

            if (autoStartNow)
                StartCoroutine(rou);

            return rou;
        }

        /// <summary>
        /// 停止所有协程
        /// </summary>
        public void StopAll()
        {
            List<IRoutineHandle> tempLst = new List<IRoutineHandle>();
            foreach (var routine in mRoutineLst)
                tempLst.Add(routine);

            foreach (var routine in tempLst)
                routine.Stop();

            mRoutineLst.Clear();
        }

        /// <summary>
        /// 开启协程（内部使用，不对外提供）
        /// </summary>
        /// <param name="handle"></param>
        public void StartCoroutine(IRoutineHandle handle)
        {
            if (mMono == null) return;
            mMono.StartCoroutine(handle.SelfRoutine);
            mRoutineLst.Add(handle);
        }

        /// <summary>
        /// 关闭协程（内部使用，不对外提供）
        /// </summary>
        /// <param name="handle"></param>
        public void StopCoroutine(IRoutineHandle handle)
        {
            if (mMono == null) return;
            if (!mRoutineLst.Contains(handle)) return;

            mMono.StopCoroutine(handle.SelfRoutine);
            mRoutineLst.Remove(handle);
            DespawnCoroutine(handle);
        }

        /// <summary>
        /// 回收协程（内部使用，不对外提供）
        /// </summary>
        public void DespawnCoroutine(IRoutineHandle handle)
        {
            mRoutinePool.Despawn(handle); //此处只回收，不释放，否则会报错
        }
    }

    /// <summary>
    /// 协程状态
    /// </summary>
    public enum RoutineState
    {
        /// <summary>
        /// 等待首次开始执行
        /// </summary>
        Waiting,

        /// <summary>
        /// 正在执行
        /// </summary>
        Running,

        /// <summary>
        /// 暂停
        /// </summary>
        Pause,

        /// <summary>
        /// 结束、停止
        /// </summary>
        Stop,
    }
}